#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP) // 不能使用sizeof()
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP) // 不能使用sizeof()

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

//-------------------------------------------------这就是表示层---------------------------------------------------------------------------
// "x op y" -> "content_len"\r\n"x op y"\r\n
// "exitcode result" -> "content_len"\r\n"exitcode result"\r\n
// 对这面这些指定协议
std::string enLength(const std::string &text)
{
    std::string send_string = std::to_string(text.size()); // conten_len
    send_string += LINE_SEP;                               //"\r\n"
    send_string += text;                                   //"x op y"
    send_string += LINE_SEP;                               //"\r\n"

    return send_string;
}
//"content_len"\r\n"exitcode result"\r\n
// 对指定的协议进行解读
//输出型参数
bool deLength(const std::string &package, std::string *text)
{
    auto pos = package.find(LINE_SEP);
    if (pos == std::string::npos)
        return false;
    std::string text_len_string = package.substr(0, pos);
    int text_len = std::stoi(text_len_string);
    *text = package.substr(pos + LINE_SEP_LEN, text_len);

    return true;
}

// 请求数据处理
class Request
{
public:
    Request() : x(0), y(0), op(0)
    {
    }
    Request(int x_, int y_, char op_) : x(x_), y(y_), op(op_)
    {
    }
    // 对服务器发的消息进行   序列化
    // 输出型     ----------------------客户端->网络--------------------------------------------
    bool serialize(std::string *out)
    {
        // 1 + 1-> "1 + 1"字符串
        Json::Value root;
        root["first"] = x;
        root["second"] = y;
        root["oper"] = op;

        Json::FastWriter writer;
        *out = writer.write(root);

        return true;
    }
    //----------------------------------------------------------------------------------------
    // 对网络传过来的数据进行反序列化
    // 输入型   -------------------------网络-->服务端-------------------------------------------
    bool deserialize(const std::string &in)
    {
        // 字符串"1 + 1" ————> 1 + 1
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        x = root["first"].asInt(); // 转为整型
        y = root["second"].asInt();
        op = root["oper"].asInt();
    }
    //-----------------------------------------------------------------------------------------
public:
    // x op y  // 1 + 1
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response() : exitcode(0), result(0)
    {
    }
    Response(int exitcode_, int result_) : exitcode(exitcode_), result(result_)
    {
    }
    // 序列化，输出型参数，服务器计算出结果后，发往客户端
    //-------------------------------------服务端->网络-------------------------------------------
    bool serialize(std::string *out)
    {
        Json::Value root;
        root["exitcode"] = exitcode;
        root["result"] = result;

        Json::FastWriter writer;
        *out = writer.write(root);

        return true;
    }
    //--------------------------------------------------------------------------------------------

    // 网络到了客户端这里，数据到了，客户端要拿到数据，进行反序列化
    //------------------------------------网络->客户端---------------------------------------------
    bool deserialize(const std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        exitcode = root["exitcode"].asInt();
        result = root["result"].asInt();

        return true;
    }

public:
    int exitcode; // 计算出问题的原因
    int result;   // 计算的结果
};

//------------------------------------------------------------------------------------------------------------------------------------
// "content_len"\r\n"x op y"\r\n"content_len"\r\n"x op y"\r\n"content_len"\r\n"x op
// 输出型 *text
// 这一步只是在网络中根据协议读取一份完整的报文
bool recvPackage(int sock, std::string &inbuffer, std::string *text)
{
    char buffer[1024];
    while (true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            inbuffer += buffer;
            auto pos = inbuffer.find(LINE_SEP);
            if (pos == std::string::npos)
                continue;
            std::string text_len_string = inbuffer.substr(0, pos);
            int text_len = std::stoi(text_len_string);
            int total_len = text_len_string.size() + 2 * LINE_SEP_LEN + text_len;

            if (total_len > inbuffer.size())
                continue;

            // 到这里，inbuffer中一定至少有一个完整的报文
            *text = inbuffer.substr(0, total_len);
            inbuffer.erase(0, total_len);

            break;
        }
        else
            return false;
    }
    return true;
}